package main

import (
	"fmt"
	"github.com/akavel/polyclip-go"
	"image"
	"image/color"
	"image/draw"
	"image/png"
	"log"
	"math"
	"os"
)

const (
	dx  = 300
	dy  = 500
	img = "a.png"
)

func main() {
	fmt.Println("Start")

	t1 := Triangle{PointA: Point{X: 100, Y: 80}, PointB: Point{120, 50}, PointC: Point{20, 20}}
	t2 := Triangle{PointA: Point{X: 112, Y: 180}, PointB: Point{194, 116}, PointC: Point{100, 149}}

	var blue color.Color = color.RGBA{210, 210, 200, 255}

	//创建画板
	imgfile, _ := os.Create(img)
	defer imgfile.Close()

	// 新建一个 指定大小的 RGBA位图
	img := image.NewNRGBA(image.Rect(0, 0, dx, dy))
	draw.Draw(img, img.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)

	drawline(t1.PointA.X, t1.PointA.Y, t1.PointB.X, t1.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 0, 0, 255}) })
	drawline(t1.PointA.X, t1.PointA.Y, t1.PointC.X, t1.PointC.Y, func(x, y int) { img.Set(x, y, color.RGBA{0, 255, 0, 255}) })
	drawline(t1.PointC.X, t1.PointC.Y, t1.PointB.X, t1.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 255, 255, 255}) })

	drawline(t2.PointA.X, t2.PointA.Y, t2.PointB.X, t2.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 0, 0, 255}) })
	drawline(t2.PointA.X, t2.PointA.Y, t2.PointC.X, t2.PointC.Y, func(x, y int) { img.Set(x, y, color.RGBA{0, 255, 0, 255}) })
	drawline(t2.PointC.X, t2.PointC.Y, t2.PointB.X, t2.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 255, 255, 255}) })

	//划线
	for i := 0; i < dy; i++ {
		img.Set(0, i, color.Black)
		img.Set(dx-1, i, color.Black)
	}
	d2 := dy / 2
	for i := 0; i < dx; i++ {
		img.Set(i, 0, color.Black)
		img.Set(i, dy-1, color.Black)
		img.Set(i, d2, color.Black)
	}

	//计算边长
	t1.calcSideLen()
	t2.calcSideLen()

	fmt.Println("三角形1：", t1)
	fmt.Println("三角形2：", t2)

	//偏移图形
	t1.PointA.Y += dy / 2
	t1.PointB.Y += dy / 2
	t1.PointC.Y += dy / 2

	t1.PointA.X += dx / 2
	t1.PointB.X += dx / 2
	t1.PointC.X += dx / 2

	t2.PointA.Y += dy / 2
	t2.PointB.Y += dy / 2
	t2.PointC.Y += dy / 2

	//计算偏移值
	px := t2.PointB.X - t1.PointC.X
	py := t2.PointB.Y - t1.PointC.Y

	t2.PointA.Y -= py
	t2.PointB.Y -= py
	t2.PointC.Y -= py

	t2.PointB.X -= px
	t2.PointC.X -= px
	t2.PointA.X -= px

	drawline(t1.PointA.X, t1.PointA.Y, t1.PointB.X, t1.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 0, 0, 255}) })
	drawline(t1.PointA.X, t1.PointA.Y, t1.PointC.X, t1.PointC.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 0, 0, 255}) })
	drawline(t1.PointC.X, t1.PointC.Y, t1.PointB.X, t1.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{255, 0, 0, 255}) })

	drawline(t2.PointA.X, t2.PointA.Y, t2.PointB.X, t2.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{0, 255, 0, 255}) })
	drawline(t2.PointA.X, t2.PointA.Y, t2.PointC.X, t2.PointC.Y, func(x, y int) { img.Set(x, y, color.RGBA{0, 255, 0, 255}) })
	drawline(t2.PointC.X, t2.PointC.Y, t2.PointB.X, t2.PointB.Y, func(x, y int) { img.Set(x, y, color.RGBA{0, 255, 0, 255}) })

	drawline(t1.PointA.X, t1.PointA.Y, t2.PointC.X, t2.PointC.Y, func(x, y int) { img.Set(x, y, color.RGBA{0, 255, 255, 255}) })

	err := png.Encode(imgfile, img)
	if err != nil {
		log.Fatal(err)
	}
	//输出
	fmt.Println("三角形1：", t1)
	fmt.Println("三角形2：", t2)
}

//计算边长
func (t *Triangle) calcSideLen() {
	//求边1
	t.SideA = calcPointSpace(&t.PointA, &t.PointB)
	t.SideB = calcPointSpace(&t.PointA, &t.PointC)
	t.SideC = calcPointSpace(&t.PointC, &t.PointB)
}

func calcPointSpace(a *Point, b *Point) int {
	lenA := abs(a.X - b.X)
	lenB := abs(a.Y - b.Y)
	lenC := math.Hypot(float64(lenA), float64(lenB))
	return round(lenC)
}

type Putpixel func(x, y int)

func DrawPolyline(pts []polyclip.Point, brush Putpixel) {
	last := len(pts) - 1
	for i := 0; i < len(pts); i++ {
		drawline(int(pts[last].X), int(pts[last].Y), int(pts[i].X), int(pts[i].Y), brush)
		last = i
	}
}

func drawline(x0, y0, x1, y1 int, brush Putpixel) {
	dx := abs(x1 - x0)
	dy := abs(y1 - y0)
	sx, sy := 1, 1
	if x0 >= x1 {
		sx = -1
	}
	if y0 >= y1 {
		sy = -1
	}
	err := dx - dy

	for {
		brush(x0, y0)
		if x0 == x1 && y0 == y1 {
			return
		}
		e2 := err * 2
		if e2 > -dy {
			err -= dy
			x0 += sx
		}
		if e2 < dx {
			err += dx
			y0 += sy
		}
	}
}
func abs(x int) int {
	if x > 0 {
		return x
	}
	return -x
}

func round(f float64) int {
	return int(math.Floor(f + 0.5))
}

type Triangle struct {
	PointA Point
	PointB Point
	PointC Point
	SideLen
	Angle
}

type Point struct {
	X int
	Y int
}

//边长
type SideLen struct {
	SideA int
	SideB int
	SideC int
}

type Angle struct {
	AngleA int
	AngleB int
	AngleC int
}
